/**
 * Squash Merge 脚本
 * 将 feature 分支的所有提交合并成一个提交到 main
 * 同时创建 archive 分支保留历史
 */

import { program } from 'commander';
import { exec } from '../utils/exec.js';
import { Logger } from '../utils/logger.js';
import { GitUtils } from '../utils/git.js';
import config from '../utils/config.js';
import path from 'path';
import { execNodeScript } from '../utils/exec.js';
import chalk from 'chalk';
import prompts from 'prompts';

const logger = new Logger('[git:squash]');

/**
 * 执行 squash merge
 */
async function squashMerge(featureBranch) {
  // 验证参数
  if (!featureBranch) {
    showHelp();
    process.exit(1);
  }

  logger.title('开始对 <' + chalk.bold.green(featureBranch) + '> 分支执行 squash merge...');

  try {
    // 检查分支是否存在
    if (!GitUtils.branchExists(featureBranch)) {
      logger.error(`分支 <${featureBranch}> 不存在`);
      process.exit(1);
    }

    // 检查本地代码状态
    logger.spinnerStart('检查分支 <' + chalk.bold.green(featureBranch) + '> 本地代码状态');
    GitUtils.checkout(featureBranch);
    const status = exec('git status --porcelain', { silent: true });
    await logger.spinnerShamefullySleep();
    if (status.trim() !== '') {
      logger.spinnerFail('本地代码有未提交的更改，请先提交或暂存更改');
      process.exit(1);
    }
    logger.spinnerSucceed('分支 <' + chalk.bold.green(featureBranch) + '> 本地代码干净');

    logger.blank();

    // 更新 main 分支
    logger.spinnerStart('拉取 main 并同步当前分支');
    GitUtils.checkout('main');
    GitUtils.pull('origin', 'main');
    await logger.spinnerShamefullySleep();
    logger.spinnerSucceed('拉取 main 并同步当前分支完成');

    // 创建 archive 分支
    const archiveBranch = `archive/${featureBranch}`;
    logger.spinnerStart(
      '从 <' +
        chalk.bold.green(featureBranch) +
        '> 创建归档分支: <' +
        chalk.bold.green(archiveBranch) +
        '>'
    );
    exec(`git branch ${archiveBranch} ${featureBranch}`);
    await logger.spinnerShamefullySleep();
    logger.spinnerSucceed(`归档分支创建完成: <` + chalk.bold.green(archiveBranch) + '>');

    // 执行 squash merge
    logger.spinnerStart(
      '在 ' +
        chalk.bold.green('main') +
        ' 分支对 <' +
        chalk.bold.green(featureBranch) +
        '> 分支执行 ' +
        chalk.bold.yellow('squash merge')
    );
    exec(`git merge --squash ${featureBranch}`, { silent: true });
    await logger.spinnerShamefullySleep();

    // 创建提交
    logger.spinnerUpdate('对 main 分支的squash merge创建提交');
    exec(`git commit`, { silent: true });
    await logger.spinnerShamefullySleep();
    logger.spinnerSucceed(
      '完成对 ' +
        chalk.bold.green('main') +
        ' 分支的 ' +
        chalk.bold.yellow('squash merge') +
        ' 并创建' +
        chalk.bold.yellow('提交')
    );

    // 推送分支
    const responsePush = await prompts({
      type: 'confirm', // 提示类型为确认
      name: 'pushBranchs', // 存储用户回答的属性名
      message: '是否推送 main 和 archive 分支？', // 提示给用户的问题
      initial: true, // 默认选项为 true (是)
    });
    let pushSuccess = false;
    if (responsePush.pushBranchs === true) {
      // 推送 main 分支
      logger.spinnerStart(`推送 main 分支`);
      exec(`git push origin main`, { silent: true });
      await logger.spinnerShamefullySleep();
      logger.spinnerSucceed(`完成` + chalk.bold.green('推送 main') + ' 分支');

      // 推送 archive 分支
      logger.spinnerStart(`推送 archive 分支: <` + chalk.bold.green(archiveBranch) + '>');
      exec(`git push origin ${archiveBranch}`, { silent: true });
      await logger.spinnerShamefullySleep();
      logger.spinnerSucceed(
        '完成' +
          chalk.bold.green('推送 archive') +
          ' 分支: <' +
          chalk.bold.green(archiveBranch) +
          '>'
      );
      pushSuccess = true;
    } else if (responsePush.pushBranchs === false) {
      logger.warning('用户选择不推送分支');
    } else {
      logger.warning('用户取消了推送分支的提示。');
    }

    // 清理分支
    const responseCleanup = await prompts({
      type: 'confirm', // 提示类型为确认
      name: 'cleanupBranchs', // 存储用户回答的属性名
      message: '是否清理本地和远端分支？', // 提示给用户的问题
      initial: true, // 默认选项为 true (是)
    });
    let cleanupSuccess = false;
    if (responseCleanup.cleanupBranchs === true) {
      const scriptPath = path.join(config.rootDir, '.scripts/git/cleanup-after-pr.js');
      try {
        await execNodeScript(scriptPath, [featureBranch]);
        cleanupSuccess = true;
      } catch (error) {
        logger.error(`没能清理 ${featureBranch} 分支`);
        logger.error(error.message);
      }
    } else if (responseCleanup.cleanupBranchs === false) {
      logger.warning('用户选择不清理分支');
    } else {
      logger.warning('用户取消了清理分支的提示。');
    }

    logger.blank();

    // 完成 并输出报告
    logger.success('成功执行 squash merge');
    logger.success(`分支合并到: ` + chalk.bold.green('main'));
    logger.success(
      `成功将 <` + chalk.bold(featureBranch) + '> 历史归档到: <' + chalk.bold(archiveBranch) + '>'
    );
    if (responsePush.pushBranchs === true) {
      if (pushSuccess) {
        logger.success(`成功推送 main 和 archive 分支: <` + chalk.bold(archiveBranch) + '>');
      } else {
        logger.error(
          '用户选择推送 ' +
            chalk.bold('main') +
            ' 和 ' +
            chalk.bold('archive') +
            ' 分支，但是，推送失败'
        );
      }
    } else if (responsePush.pushBranchs === false) {
      logger.warning('用户选择不推送分支');
    } else {
      logger.warning('用户取消了推送分支的提示。');
    }
    if (responseCleanup.cleanupBranchs === true) {
      if (cleanupSuccess) {
        logger.success(
          `成功清理本地分支: <` +
            chalk.bold(featureBranch) +
            '> 和 <' +
            chalk.bold(archiveBranch) +
            '>'
        );
        logger.success(`成功清理远端分支: <` + chalk.bold(featureBranch) + '>');
      } else {
        logger.error(
          `用户选择清理本地和远端分支<` +
            chalk.bold(featureBranch) +
            '> 和 <' +
            chalk.bold(archiveBranch) +
            '>，但是，清理失败'
        );
      }
    } else if (responseCleanup.cleanupBranchs === false) {
      logger.warning('用户选择不清理分支');
    } else {
      logger.warning('用户取消了清理分支的提示。');
    }
  } catch (error) {
    logger.error('合并失败');
    logger.error(error.message);
    process.exit(1);
  }
}

/**
 * 显示帮助信息
 */
function showHelp() {
  logger.title('Git Squash Merge');
  logger.info('使用命令: pnpm git:squash <branch>');
  logger.blank();
  logger.info('Commit Types:');
  const types = [
    'build    - 构建系统或外部依赖的更改',
    'ci       - CI 配置或脚本的更改',
    'docs     - 文档',
    'perf     - 性能优化',
    'refactor - 重构',
    'revert   - 回滚之前的提交',
    'test     - 测试',
    'chore    - 维护',
    'feat     - 新功能',
    'fix      - 修复 bug',
  ];
  logger.list(types);
  logger.blank();
  logger.info('示例:');
  logger.info('  pnpm git:finish feature/login"');
}

// CLI 配置
program
  .name('git:squash')
  .description('Squash merge a branch into main with archive')
  .argument('<branch>', 'branch to merge')
  .action(squashMerge)
  .on('--help', showHelp);

program.parse();
